home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#39 (Dec 88)
/
Twindow
/
TWindows.c
< prev
next >
Wrap
Text File
|
1988-04-29
|
65KB
|
2,266 lines
/*
* TWindows.c
*
* C source of an extended Window Manager that supports tool windows;
* these are windows that always float on top, for palettes and tools.
*
* Written in MPW C 2.0
*
* Copyright Thomas Fruin 1988
* All rights reserved.
*
* fruin@hlerul5.BITNET University of Leiden
* thomas@uvabick.UUCP University of Amsterdam
* dibs@well.UUCP
* hol0066.AppleLink
* 2:508/15.FidoNet The Netherlands
*/
/*
* T O O L B O X I N C L U D E S
*
* Header files for the Toolbox data types and functions
* used in this source file.
*/
#include <Types.h>
#include <Memory.h>
#include <Quickdraw.h>
#include <Events.h>
#include <Windows.h>
#include <ToolUtils.h>
#include <OSUtils.h>
#include <Resources.h>
/*
* T O O L B O X D E F I N I T I O N S
*
* Definitions of low memory global variables:
*
* o GrayRgn is a handle to the current desktop region, a region
* encompassing the complete desktop space ( possibly spread
* out over more than one screen). Only needed on the old 64K
* ROM Macintosh and the Mac XL, since there is the new func-
* tion GetGrayRgn that also returns this handle.
* o WindowList is a pointer to the very first window. By tra-
* versing the nextWindow fields in each WindowRecord, you can
* access each window in turn. This global is more than just
* FrontWindow(), because the function only returns the first
* _visible_ window.
*/
#define GrayRgn (*(RgnHandle *)0x9EE)
#define WindowList (*(WindowPeek *)0x9D6)
/*
* D E F I N I T I O N S
*
* The constants used in this source file.
*/
/* Defines LONGINT, INTEGER, the windowKind constants
and the externally callable TWindow Manager functions. */
#include <TWindows.h>
/* Result codes describing window positions, as
returned by the function GetWPosition. */
#define alone 0 /* no other windows visible */
#define beforeDialog 1 /* it is before the frontmost */
/* window, which is a dialog */
#define beforeSystem 2 /* it is before the frontmost */
/* window, which is a DA */
#define beforeTool 3 /* it is before the frontmost */
/* window, which is a tool */
#define beforeDocument 4 /* it is before the frontmost */
/* window, which is a document */
#define behindFrontSystem 5 /* it is behind the frontmost */
/* window, which is a DA */
#define betweenTools 6 /* it is among the tool windows */
#define behindTools 7 /* it is behind all tool windows, */
/* but before document windows */
#define behindSystem 8 /* it is behind all tool windows, */
/* and behind a DA */
#define betweenDocuments 9 /* it is behind the frontmost */
/* document window */
/* Miscellaneous */
#define deactivFlag 0 /* modifiers for deactivate event */
#define noDrag -32768 /* possible result of DragGrayRgn */
#define invisible false /* when calling NewWindow */
#define curVersion 1 /* current version of SysEnvirons */
#define postponeCalc true /* postpone CalcVisBehind call */
#define normalCalc false /* do normal CalcVisBehind call */
/*
* T Y P E S
*
* Type definitions of some structures.
*/
/* The WINDData structure matches the structure of a WIND resource
in a resource file. It is used to access the various fields of
the WIND resource after it has been read in from the file. */
struct WINDRecord
{
Rect boundsRect;
INTEGER procID;
Boolean visible;
char filler1;
Boolean goAwayFlag;
char filler2;
LONGINT refCon;
Str255 title;
};
typedef struct WINDRecord WINDData;
typedef struct WINDRecord *WINDPtr;
typedef struct WINDRecord **WINDHandle;
/* The WDEFHeader structure matches the structure of the (optional)
header of a window definition procedure resource. */
struct WDEFRecord
{
INTEGER branch;
INTEGER flags;
LONGINT type;
INTEGER ID;
INTEGER version;
};
typedef struct WDEFRecord WDEFHeader;
typedef struct WDEFRecord *WDEFPtr;
typedef struct WDEFRecord **WDEFHandle;
/*
* G L O B A L S
*
* The TWindow Manager's globals. ToBeActivated and toBeDeactivated hold
* the next window to be activated and deactivated respectively. FrontTool-
* Window, backToolWindow and frontDocWindow are pointers to the frontmost
* visible tool window, the backmost visible tool window, and the frontmost
* visible document window. FirstRgn and secondRgn are region handles that
* are used in several places in the TWindow Manager,but are allocated only
* once for efficiency. TheWorld is a standard SysEnvirons data structure
* that describes the capabilities of the system we are running on.
*/
static WindowPeek toBeActivated,
toBeDeactivated,
frontToolWindow,
backToolWindow,
frontDocWindow;
static RgnHandle firstRgn,
secondRgn;
static SysEnvRec theWorld;
/*
* T I N I T W I N D O W S
*
* TInitWindows must be called before any other TWindow Manager functions
* are called. It is used to initialize the global variables.
*
* Note that TInitWindows is no replacement for InitWindows. It does _not_
* call InitWindows; that is up to the calling application.
*
* Parameters:
*
* <none>
*
* Local variables and used functions:
*
* OSErr err; result of SysEnvirons call
*
* Global variables and constants:
*
* WindowPeek frontToolWindow, frontmost tool window
* backToolWindow, backmost tool window
* frontDocWindow, frontmost document window
* toBeActivated, window that needs activating
* toBeDeactivated; window that needs deactivating
* RgnHandle firstRgn, region used for various purposes
* secondRgn; region used for various purposes
*/
void
TInitWindows()
{
OSErr err;
frontToolWindow =
backToolWindow =
frontDocWindow =
toBeDeactivated =
toBeActivated = nil;
firstRgn = NewRgn();
secondRgn = NewRgn();
err = SysEnvirons( curVersion, &theWorld );
}
/*
* T G E T N E W W I N D O W
*
* TGetNewWindow is a special version of the GetNewWindow call for creating
* tool windows and documents windows, as specified by a window template in
* a resource file. If the window template could not be read in from the
* resource file, or the window definition function for this window could
* not be read into memory, nil is returned. The window's windowKind field
* is set to the value of the windowKind parameter. If you want this window
* to behave as a tool window, pass the constant toolKind as windowKind.
*
* TGetNewWindow first calls GetResource to get the window template into
* memory. In then calls NewWindow to create the window, invisible. If the
* caller specified a visible window ( by setting the visible field in the
* template to true), the function TShowWindow is called to make it visible
* and to update any global variables,post activate events and to make sure
* the window appears in its proper plane.
*
* Parameters:
*
* IN:
*
* INTEGER windowKind; type of window to create;
*
* The rest of TGetNewWindow's parameters are the same as the
* parameters for the standard toolbox function GetNewWindow.
*
* OUT:
*
* WindowPtr TGetNewWindow(); the new window
*
* Local variables and used functions:
*
* Rect boundsRect; NewWindow parameter
* Str255 title; NewWindow parameter
* Boolean visible; NewWindow parameter
* INTEGER procID; NewWindow parameter
* Boolean goAwayFlag; NewWindow parameter
* LONGINT refCon; NewWindow parameter
* WindowPtr theWindow, the new window
* WINDHandle theWINDHandle; handle to window template
* WINDPtr theWINDPtr; pointer to window template
*
* Constants:
*
* Boolean invisible; false, so window is invisible
*/
WindowPtr
TGetNewWindow( windowKind, windowID, wStorage, behind )
INTEGER windowKind;
INTEGER windowID;
Ptr wStorage;
WindowPtr behind;
{
Rect boundsRect;
Str255 title;
Boolean visible;
INTEGER procID;
Boolean goAwayFlag;
LONGINT refCon;
WindowPtr theWindow;
WINDHandle theWINDHandle;
WINDPtr theWINDPtr;
/* Read the window template in from the resource file. */
theWINDHandle = ( WINDHandle )GetResource( 'WIND', windowID );
if ( theWINDHandle != nil )
{
/* Copy the window template values to variables in
preparation of a NewWindow call. */
theWINDPtr = *theWINDHandle;
boundsRect = theWINDPtr->boundsRect;
visible = theWINDPtr->visible;
procID = theWINDPtr->procID;
goAwayFlag = theWINDPtr->goAwayFlag;
refCon = theWINDPtr->refCon;
if ( theWINDPtr->title.length == 0 )
title.length = 0;
else
BlockMove( &( theWINDPtr->title ), &title,
( Size )theWINDPtr->title.length + 1 );
p2cstr( &title );
/* Release the used resource. Create the window, but
make it invisible. */
ReleaseResource(( Handle )theWINDHandle );
theWindow = NewWindow( wStorage, &boundsRect, &title, invisible,
procID, behind, goAwayFlag, refCon );
if ( theWindow != nil )
{
/* Set the windowKind field. If the window is a tool,
make sure it is highlighted. If the user originally
specified a visible window in the window template,
show it now. */
(( WindowPeek )theWindow )->windowKind = windowKind;
if ( visible != false )
TShowWindow( theWindow );
}
}
else
theWindow = nil;
return( theWindow );
}
/* End of TGetNewWindow */
/*
* T N E W W I N D O W
*
* TNewWindow is a special version of the NewWindow call for creating tool
* windows and documents windows. If the window definition function for
* this window could not be read into memory, nil is returned. The window's
* windowKind field is set to the value of the windowKind parameter. If you
* want this window to behave as a tool window, pass the constant toolKind
* as windowKind.
*
* TNewWindow calls NewWindow to create the window, invisible. If a visible
* window was specified by the caller, the function TShowWindow is called
* to make it visible and to update any global variables, post activate
* events and to make sure the window appears only in the plane it should
* be in.
*
* Parameters:
*
* IN:
*
* INTEGER windowKind; type of window to create
*
* The rest of TNewWindow's parameters are the same as the
* parameters for the standard toolbox function NewWindow.
*
* OUT:
*
* WindowPtr TNewWindow(); the new window
*
* Local variables and used functions:
*
* WindowPtr theWindow; the new window
*
* Constants:
*
* Boolean invisible; false, so window is invisible
*/
WindowPtr
TNewWindow( windowKind, wStorage, boundsRect, title,
visible, procID, behind, goAwayFlag, refCon )
INTEGER windowKind;
Ptr wStorage;
Rect *boundsRect;
char *title;
Boolean visible;
INTEGER procID;
WindowPtr behind;
Boolean goAwayFlag;
LONGINT refCon;
{
WindowPtr theWindow;
/* Create the window, invisible. */
theWindow = NewWindow( wStorage, boundsRect, title, invisible,
procID, behind, goAwayFlag, refCon );
if ( theWindow != nil )
{
/* Set the windowKind field. If the window is a tool,
make sure it is highlighted. If the user specified
a visible window, show it now. */
(( WindowPeek )theWindow )->windowKind = windowKind;
if ( visible != false )
TShowWindow( theWindow );
}
return( theWindow );
}
/* End of TNewWindow */
/*
* T C L O S E W I N D O W
*
* TCloseWindow is a replacement for the standard CloseWindow function
* in the toolbox. It calls THideWindow first, to make the window in-
* visible. Then it calls CloseWindow to close the window. Finally it
* checks if there is a pending deactivate event for the window. If
* there is, it removes the deactivate event, since it is no longer
* necessary.
*
* Parameters:
*
* IN:
*
* WindowPtr theWindow; window to be closed
*
* Global variables:
*
* WindowPtr toBeDeactivated; window that needs deactivating
*/
void
TCloseWindow( theWindow )
WindowPtr theWindow;
{
THideWindow( theWindow );
CloseWindow( theWindow );
if ( theWindow == toBeDeactivated )
toBeDeactivated = nil;
}
/* End of TCloseWindow */
/*
* T D I S P O S E W I N D O W
*
* TDisposeWindow is a replacement for the standard DisposeWindow trap
* in the toolbox. It calls THideWindow first, to make the window in-
* visible. Then it calls DisposeWindow to dispose of the windowrecord.
* Finally it checks if there is a pending deactivate event for the
* window. If there is, it removes the deactivate event, since it is
* no longer necessary.
*
* Parameters:
*
* IN:
*
* WindowPtr theWindow; window to be disposed of
*
* Global variables:
*
* WindowPtr toBeDeactivated; window that needs deactivating
*/
void
TDisposeWindow( theWindow )
WindowPtr theWindow;
{
THideWindow( theWindow );
DisposeWindow( theWindow );
if ( theWindow == toBeDeactivated )
toBeDeactivated = nil;
}
/* End of TDisposeWindow */
/*
* T S E L E C T W I N D O W
*
* TSelectWindow is a replacement for the Toolbox routine SelectWindow.
* It moves the selected document window to the front, just behind the
* the backmost tool window, highlights it, and marks it for activation
* for the next TGetNextEvent call. The current frontmost window is un-
* highlighted, and is marked for deactivation. Tool windows can also
* be selected when the user clicks them: they are moved completely to
* the front, just like SelectWindow does.
*
* If a desk accessory is in front when a window is selected, all the
* tool windows and the frontmost document window will be moved on top
* of the desk accessory.
*
* Parameters:
*
* IN:
*
* WindowPtr theWindow; window to be selected
*
* Local variables and used functions:
*
* void BringForward(); brings a window forward behind
* another
* WindowPeek thePWindow, WindowPeek version of the window
* theFrontWindow, frontmost window
* NextVisWindow(), next visible window in the list
* PrevVisWindow(); previous visible window in the list
* INTEGER theWKind, windowKind of the theWindow
* frontWKind; windowKind of the theFrontWindow
* Boolean toolsVisible, true if tool windows are visible
* BringToolsForward();brings all tool windows in front,
* when there's a DA on top
*
* Global variables:
*
* WindowPeek frontToolWindow, frontmost tool window
* backToolWindow, backmost tool window
* frontDocWindow, frontmost document window
* toBeActivated, window that needs activating
* toBeDeactivated; window that needs deactivating
*
* Constants:
*
* INTEGER systemKind, windowKind value for DAs
* toolKind; windowKind value for tool windows
*/
void
TSelectWindow( theWindow )
WindowPtr theWindow;
{
void BringForward();
WindowPeek thePWindow,
theFrontWindow,
NextVisWindow(),
PrevVisWindow();
INTEGER theWKind,
frontWKind;
Boolean toolsVisible,
BringToolsForward();
/* Initialize some variables. */
thePWindow = ( WindowPeek )theWindow;
theFrontWindow = ( WindowPeek )FrontWindow();
theWKind = TGetWKind( theWindow );
frontWKind = TGetWKind(( WindowPtr )theFrontWindow );
if ( theWKind == toolKind )
{
if ( frontWKind == systemKind )
{
/* Window is a tool window, with a desk accessory
on top. Select the tool (to unhighlight the
DA). Use BringToolsForward to move the rest of
the tools. Move a possible document window to
the front with BringForward. Update globals. */
SelectWindow( theWindow );
(void)BringToolsForward( thePWindow );
if ( frontDocWindow != nil )
{
frontDocWindow->hilited = true;
BringForward( frontDocWindow, backToolWindow,
normalCalc );
toBeActivated = frontDocWindow;
}
frontToolWindow = thePWindow;
}
else
{
/* Window is a tool window, and no desk accessory
on top. Find the new backToolWindow if that is
necessary, then bring our window to the front.
Update our globals. */
if ( thePWindow != frontToolWindow )
{
if ( thePWindow == backToolWindow )
{
backToolWindow = NextVisWindow( toolKind, thePWindow );
if ( backToolWindow == nil )
backToolWindow = PrevVisWindow( thePWindow );
}
BringToFront( theWindow );
frontToolWindow = thePWindow;
}
}
}
else if ( theWKind == userKind )
{
if ( frontWKind == systemKind )
{
/* Window is a document window (or a modeless dialog
window), with a desk accessory on top. Use Bring-
ToolsForward to move the tools to the front. This
unhighlights the desk accessory. Finish by moving
the document window to the front (using SelectWindow
if there were no tools to unhighlight the DA). */
toolsVisible = BringToolsForward(( WindowPeek )inFront );
if ( toolsVisible == false )
SelectWindow( theWindow );
else
{
thePWindow->hilited = true;
BringForward( theWindow, backToolWindow, normalCalc );
}
toBeActivated =
frontDocWindow = thePWindow;
}
else
{
/* Window is a document window (or a modeless dialog
window), and no desk accessory on top. If it isn't
already the frontmost window, use SelectWindow to
bring it to the front if there are no tool windows
visible, otherwise use BringForward to move the
document window just behind the backToolWindow. */
if ( thePWindow != frontDocWindow )
{
if ( frontToolWindow == nil )
SelectWindow( theWindow );
else
{
HiliteWindow(( WindowPtr )frontDocWindow, false );
thePWindow->hilited = true;
BringForward( thePWindow, backToolWindow,
normalCalc );
}
toBeDeactivated = frontDocWindow;
toBeActivated =
frontDocWindow = thePWindow;
}
}
}
}
/* End of TSelectWindow */
/*
* T H I D E W I N D O W
*
* THideWindow is a replacement for the toolbox routine HideWindow. It
* is used to make a window invisible ( it has no effect if the window
* is already invisible). If the window is the frontmost document win-
* dow and there is a document window behind it, THideWindow will high-
* light that window and post an activate event for it. If the window
* behind it is a desk accessory and there are still tool windows in
* front, the desk accessory will be brought in front of the tools.
*
* THideWindow uses GetWPosition to find out the exact position of the
* window with respect to other windows on the desktop. It then takes
* specific action for each type of position, such as moving windows to
* an allowed location first, or highlighting windows manually, posting
* activate events and updating the global variables frontToolWindow,
* backToolWindow and frontDocWindow.
*
* Parameters:
*
* IN:
*
* WindowPtr theWindow; window to be hidden
*
* Local variables and used functions:
*
* WindowPeek thePWindow, WindowPeek version of theWindow
* behindWindow; window behind theWindow when
* theWindow is behindTools
* INTEGER theWKind, the window's windowKind
* thePosition, the window's relative position
* GetWPosition(); determines window's position
* void HiliteTools(); (Un)highlights all the tools
*
* Global variables:
*
* WindowPeek frontToolWindow, frontmost tool window
* backToolWindow, backmost tool window
* frontDocWindow, frontmost document window
* toBeActivated, window that needs activating
* toBeDeactivated; window that needs deactivating
*
* Constants:
*
* INTEGER systemKind, windowKind for DA windows
* toolKind, windowKind for tool windows
* alone, no other windows visible
* beforeDialog, it is before the frontmost window,
* which is a dialog window
* beforeSystem, it is before the frontmost window,
* which is a system window
* beforeTool, it is before the frontmost window,
* which is a tool window
* beforeDocument, it is before the frontmost window,
* which is a document window
* behindFrontSystem, it is behind the frontmost window,
* which is a system window
* betweenTools, it is among the tool windows
* behindTools, it is behind all the tool windows
* but before any document windows
* behindSystem, it is behind all the tool windows
* and behind a system window
* betweenDocuments; it is behind the first document
* window
*/
void
THideWindow( theWindow )
WindowPtr theWindow;
{
WindowPeek thePWindow,
behindWindow;
INTEGER theWKind,
thePosition,
frontWKind,
GetWPosition();
void HiliteTools();
if ((( WindowPeek )theWindow )->visible != false )
{
/* Save some window values, for later unhighlighting
and deactivating. */
thePWindow = ( WindowPeek )theWindow;
theWKind = TGetWKind( theWindow );
thePosition = GetWPosition( thePWindow, &frontWKind );
/* Hide the window, and update the desktop
according to the window's position. */
if ( theWKind == toolKind )
{
/* The window is a tool window. */
switch( thePosition )
{
case alone:
case beforeSystem:
HideWindow( theWindow );
frontToolWindow =
backToolWindow = nil;
break;
case beforeTool:
ShowHide( theWindow, false );
frontToolWindow = ( WindowPeek )FrontWindow();
break;
case behindFrontSystem:
ShowHide( theWindow, false );
frontToolWindow =
NextVisWindow( toolKind, thePWindow );
if ( frontToolWindow == nil )
backToolWindow = nil;
break;
case beforeDocument:
frontToolWindow =
backToolWindow = nil;
ShowHide( theWindow, false );
break;
/* NOTE: no behindTools possible! */
case betweenTools:
ShowHide( theWindow, false );
if ( thePWindow == backToolWindow )
backToolWindow = PrevVisWindow( thePWindow );
break;
}
}
else if ( theWKind == userKind )
{
/* The window is a document window
(or a modeless dialog window). */
thePWindow->hilited = false;
switch( thePosition )
{
case alone:
case beforeSystem:
toBeDeactivated = thePWindow;
frontDocWindow = nil;
case betweenDocuments:
HideWindow( theWindow );
break;
case beforeDocument:
HideWindow( theWindow );
toBeDeactivated = thePWindow;
toBeActivated =
frontDocWindow = ( WindowPeek )FrontWindow();
break;
case behindFrontSystem:
ShowHide( theWindow, false );
frontDocWindow =
NextVisWindow( userKind, theWindow );
break;
case behindTools:
frontDocWindow =
NextVisWindow( userKind, theWindow );
behindWindow =
NextVisWindow( anyKind, theWindow );
ShowHide( theWindow, false );
if ( behindWindow == nil )
toBeDeactivated = thePWindow;
else
{
if ( behindWindow != frontDocWindow )
{
if ( frontWKind == toolKind )
{
HiliteTools( false );
SelectWindow(( WindowPtr )behindWindow );
toBeDeactivated = thePWindow;
}
if ( frontDocWindow != nil )
BringForward( frontDocWindow,
backToolWindow, normalCalc );
}
else
{
if ( frontWKind == toolKind )
{
HiliteWindow( frontDocWindow, true );
toBeActivated = frontDocWindow;
toBeDeactivated = thePWindow;
}
}
}
break;
}
}
else
{
/* The window is a modal dialog window. */
switch( thePosition )
{
case alone:
case beforeSystem:
case beforeDialog:
HideWindow( theWindow );
break;
case beforeTool:
case beforeDocument:
ShowHide( theWindow, false );
HiliteTools( true );
if ( frontDocWindow != nil )
{
toBeDeactivated = thePWindow;
toBeActivated = frontDocWindow;
HiliteWindow(( WindowPtr )frontDocWindow, true );
}
break;
}
}
}
}
/* End of THideWindow */
/*
* T S H O W W I N D O W
*
* TShowWindow is a replacement for the standard ShowWindow function in
* the toolbox. Like ShowWindow, TShowWindow makes the window visible
* if it's not already visible (otherwise it has no effect). It also
* makes very sure that the window will appear in an allowed position
* for that window after it's been made visible.
*
* TShowWindow calls GetWPosition to find out the exact position of the
* window with respect to other windows on the desktop. It then takes
* specific action for each type of position, such as moving windows to
* an allowed location first, or highlighting windows manually, posting
* activate events and updating the global variables front- and back-
* ToolWindow and frontDocWindow.
*
* Parameters:
*
* IN:
*
* WindowPtr theWindow; window to be shown
*
* Local variables:
*
* WindowPeek thePWindow, WindowPeek version of theWindow
* theFrontWindow; frontmost visible window
* INTEGER theWKind, theWindow's windowKind
* frontWKind, windowKind of theFrontWindow
* thePosition, the window's relative position
* GetWPosition(); determines window's position
* Boolean toolsExist; true if tools are visible
*
* Used functions:
*
* WindowPeek PrevVisWindow(); window in front of given window
* Boolean BringToolsForward();brings all tools forward
* void BringForward(), brings a window forward behind
* another
* HiliteTools(); (Un)highlights all the tools
*
* Global variables:
*
* WindowPeek frontToolWindow, frontmost tool window
* backToolWindow, backmost tool window
* frontDocWindow, frontmost document window
* toBeActivated, window that needs activating
* toBeDeactivated; window that needs deactivating
*
* Constants:
*
* INTEGER systemKind, windowKind for DA windows
* toolKind, windowKind for tool windows
* alone, no other windows visible
* beforeDialog, it is before the frontmost window,
* which is a dialog window
* beforeSystem, it is before the frontmost window,
* which is a system window
* beforeTool, it is before the frontmost window,
* which is a tool window
* beforeDocument, it is before the frontmost window,
* which is a document window
* behindFrontSystem, it is behind the frontmost window,
* which is a system window
* betweenTools, it is among the tool windows
* behindTools, it is behind all the tool windows
* but before any document windows
* behindSystem, it is behind all the tool windows
* and behind a system window
* betweenDocuments; it is behind the first document
* window
*/
void
TShowWindow( theWindow )
WindowPtr theWindow;
{
WindowPeek thePWindow,
theFrontWindow,
behind,
PrevVisWindow();
INTEGER theWKind,
frontWKind,
thePosition,
GetWPosition();
Boolean toolsExist,
BringToolsForward();
void BringForward(),
HiliteTools();
if ((( WindowPeek )theWindow )->visible == false )
{
/* The window is still invisible. */
thePWindow = ( WindowPeek )theWindow;
theFrontWindow = ( WindowPeek )FrontWindow();
theWKind = TGetWKind( theWindow );
thePosition = GetWPosition( thePWindow, &frontWKind );
if ( theWKind == toolKind )
{
/* The window is a tool window. Assume it needs
to appear highlighted (correct this later). */
thePWindow->hilited = true;
switch( thePosition )
{
case beforeSystem:
ShowWindow( theWindow );
( void )BringToolsForward( thePWindow );
if ( frontDocWindow != nil )
{
frontDocWindow->hilited = true;
BringForward( frontDocWindow,
backToolWindow, normalCalc );
toBeActivated = frontDocWindow;
}
frontToolWindow = thePWindow;
break;
case behindFrontSystem:
thePWindow->hilited = false;
case alone:
case beforeDocument:
if ( backToolWindow == nil )
backToolWindow = thePWindow;
case beforeTool:
ShowHide( theWindow, true );
frontToolWindow = thePWindow;
break;
case behindTools:
backToolWindow = thePWindow;
case betweenTools:
if ( frontWKind == systemKind )
thePWindow->hilited = false;
ShowHide( theWindow, true );
break;
case behindSystem:
SendBehind( theWindow,
( WindowPtr )backToolWindow );
if ( frontWKind == systemKind )
thePWindow->hilited = true;
ShowHide( theWindow, true );
backToolWindow = thePWindow;
break;
case betweenDocuments:
if ( backToolWindow != nil )
behind = backToolWindow;
else
{
behind = PrevVisWindow( frontDocWindow );
frontToolWindow = thePWindow;
}
if ( behind == nil )
BringToFront( theWindow );
else
{
SendBehind( theWindow, behind );
if ( frontWKind == systemKind )
thePWindow->hilited = false;
}
ShowHide( theWindow, true );
backToolWindow = thePWindow;
break;
}
}
else if ( theWKind == userKind )
{
/* The window is a document window. */
switch( thePosition )
{
case beforeSystem:
toolsExist = BringToolsForward(
( WindowPeek )inFront );
if ( toolsExist != false )
thePWindow->hilited = true;
case alone:
ShowWindow( theWindow );
toBeActivated =
frontDocWindow = thePWindow;
break;
case beforeTool:
if ( frontDocWindow != nil )
{
HiliteWindow(( WindowPtr )frontDocWindow,
false );
toBeDeactivated = frontDocWindow;
}
SendBehind( theWindow, backToolWindow );
thePWindow->hilited = true;
ShowHide( theWindow, true );
toBeActivated =
frontDocWindow = thePWindow;
break;
case beforeDocument:
/* The three steps HiliteWindow,
HiliteWindow and ShowHide could be
replaced with one call to ShowWindow,
but this gives a better visual effect.
(Try the difference.) */
HiliteWindow( frontDocWindow, false );
HiliteWindow( theWindow, true );
ShowHide( theWindow, true );
toBeDeactivated = frontDocWindow;
toBeActivated =
frontDocWindow = thePWindow;
break;
case behindFrontSystem:
if ( backToolWindow != nil )
SendBehind( theWindow,
( WindowPtr )backToolWindow );
ShowHide( theWindow, true );
frontDocWindow = thePWindow;
break;
case betweenTools:
SendBehind( theWindow,
( WindowPtr )backToolWindow );
case behindTools:
if ( frontWKind == toolKind )
{
thePWindow->hilited = true;
toBeActivated = thePWindow;
if ( frontDocWindow != nil )
{
HiliteWindow(( WindowPtr )frontDocWindow,
false );
toBeDeactivated = frontDocWindow;
}
}
ShowHide( theWindow, true );
frontDocWindow = thePWindow;
break;
case behindSystem:
SendBehind( theWindow,
( WindowPtr )backToolWindow );
if ( frontWKind == toolKind )
{
thePWindow->hilited = true;
toBeActivated = thePWindow;
}
ShowHide( theWindow, true );
frontDocWindow = thePWindow;
break;
case betweenDocuments:
ShowHide( theWindow, true );
break;
}
}
else
{
/* The window is a modal dialog window. */
switch( thePosition )
{
case alone:
case beforeSystem:
case beforeDialog:
ShowWindow( theWindow );
break;
case beforeTool:
case beforeDocument:
HiliteTools( false );
if ( frontDocWindow != nil )
{
toBeDeactivated = frontDocWindow;
HiliteWindow(( WindowPtr )frontDocWindow, false );
}
ShowHide( theWindow, true );
break;
}
}
}
}
/* End of TShowWindow */
/*
* T F R O N T W I N D O W
*
* TFrontWindow effectively replaces the Toolbox trap FrontWindow in an
* environment with tool windows. This function is not only for deter-
* mining just the frontmost visible window, but the caller can also
* specify what kind of window it wants in the wantedKind parameter.
* If there is a desk accessory or modal dialog on top, TFrontWindow
* will return a pointer to the desk accessory's or dialog's window.
*
* Parameters:
*
* IN:
*
* INTEGER wantedKind; kind of window to look for
*
* OUT:
*
* WindowPtr TFrontWindow(); frontmost document window or nil
*
* Local variables and used functions:
*
* WindowPtr theWindow; the frontmost window
* INTEGER theWKind; the front window's windowKind
*
* Global variables and constants:
*
* WindowPeek frontDocWindow, frontmost document window
* frontToolWindow; frontmost tool window
* INTEGER systemKind, windowKind value for DA windows
* toolKind, windowKind value for tool windows
* anyKind; windowKind "wildcard"
*/
WindowPtr
TFrontWindow( wantedKind )
INTEGER wantedKind;
{
WindowPtr theWindow;
INTEGER theWKind;
theWindow = FrontWindow();
theWKind = TGetWKind( theWindow );
if ( theWKind == systemKind ||
theWKind == dialogKind )
return( theWindow );
else
switch ( wantedKind )
{
case toolKind:
return(( WindowPtr )frontToolWindow );
break;
case userKind:
return(( WindowPtr )frontDocWindow );
break;
case anyKind:
return( theWindow );
break;
}
}
/* End of TFrontWindow */
/*
* T D R A G W I N D O W
*
* TDragWindow is the replacement for the Toolbox routine DragWindow.
* There are three things that DrawWindow does which are replaced in
* TDragWindow: if the window is not in front it needs to be brought to
* the front (if the command key is not being held down). This is done
* with a call to TSelectWindow.
*
* The second thing is the dragging itself. We use DragGrayRgn to draw
* a gray outline of the window (its strucRgn) around, _below_ any tool
* windows and other document windows that may be lying on top of it.
* This is accomplished by setting the clipRgn of the Window Manager
* port (the port we're drawing in) "to be the desktop intersected with
* the current clipRgn, minus the structure regions of all the windows
* in front of the given window". This is exactly what the low-level
* QuickDraw routine ClipAbove does.
*
* The third and last step is to examine the result of DragGrayRgn, and
* to move the window accordingly. Watch the frequent changing of coor-
* dinates from global to local and vice versa!
*
* Parameters:
*
* IN:
*
* WindowPtr theWindow; pointer to the window to be dragged
* EventRecord *theEvent; pointer to event that caused this
* call to TDragWindow
*
* Local variables and used functions:
*
* GrafPtr savePort, for saving the current grafport
* wPort; for holding the Window Manager port
* Rect limitRect, parameter for DragGrayRgn
* slopRect; parameter for DragGrayRgn
* RgnHandle desktopRgn; region for holding the desktop region
* LONGINT result; value DragGrayRgn returns
* INTEGER hDrag, horizontal displacement after dragging
* vDrag; vertical displacement after dragging
* Point thePoint; for calculating new position
*
* Global constants and variables:
*
* WindowPeek frontDocWindow, frontmost document window
* RgnHandle GrayRgn, low memory global holding desktop region
* firstRgn, for saving the Window Manager's clipRgn
* secondRgn; region that holds the drag outline
*/
void
TDragWindow( theWindow, theEvent, boundsRect )
WindowPtr theWindow;
EventRecord *theEvent;
Rect *boundsRect;
{
GrafPtr savePort,
wPort;
Rect limitRect,
slopRect;
RgnHandle desktopRgn;
LONGINT result;
INTEGER hDrag,
vDrag;
Point thePoint;
if (( theEvent->modifiers & cmdKey ) == false )
{
/* If the command key is not being held down, call
TSelectWindow to bring the window to the front.
(TSelectWindow will determine if this is really
necessary.) Then make sure the mouse is still
down before we start dragging. */
TSelectWindow( theWindow );
if ( StillDown() == false )
return;
}
/* Save the current port and set it to the Window
Manager port, since we're going to draw the
drag outline in this port. */
GetPort ( &savePort );
GetWMgrPort( &wPort );
SetPort ( wPort );
/* Get a handle to the current desktop region.
There is a routine for this on newer machines,
but the old 64K ROM Mac and Mac XL will still
have to get it from the low memory global GrayRgn. */
/* if ( theWorld.machineType == envMac ||
theWorld.machineType == envXL ) */
desktopRgn = GrayRgn;
/* else
desktopRgn = GetGrayRgn(); */
/* Set the clipping region to the current desktop
region, intersected with all the windows above
theWindow. */
GetClip ( firstRgn );
SetClip ( desktopRgn );
ClipAbove(( WindowPeek )theWindow );
/* Finally call DragGrayRgn to drag the outline
of the window. */
CopyRgn((( WindowPeek )theWindow )->strucRgn, secondRgn );
SetPt ( &thePoint, theEvent->where.h, theEvent->where.v );
GlobalToLocal( &thePoint );
result = DragGrayRgn( secondRgn, &thePoint, boundsRect,
boundsRect, noConstraint, ( ProcPtr )nil );
/* Restore the Window Manager port's clipRgn. */
SetClip( firstRgn );
/* Check if the user actually moved the window.
If so, call MoveWindow to move the window to
its new location. */
vDrag = HiWord( result );
hDrag = LoWord( result );
if ( !( vDrag == noDrag && hDrag == noDrag ))
{
SetPort( theWindow );
SetPt ( &thePoint, theWindow->portRect.left,
theWindow->portRect.top );
LocalToGlobal( &thePoint );
MoveWindow( theWindow, thePoint.h + hDrag,
thePoint.v + vDrag, false );
}
/* Restore the original grafport, and clear out
the region handles. */
SetPort( savePort );
SetEmptyRgn( firstRgn );
SetEmptyRgn( secondRgn );
}
/* End of TDragWindow */
/*
* T G E T N E X T E V E N T
*
* TGetNextEvent is a replacement for the Toolbox routine GetNextEvent.
* It still calls GetNextEvent, but filters the activate events and
* sometimes inserts activate events of its own. This is because the
* movement of document windows behind the tool windows goes unnoticed
* by the Window Manager, and no activate events are posted for them.
*
* If there is a true activate event in the queue, it is because either
* a window was moved completely to the front, or a desk accessory was
* opened or closed. In the latter case, the frontmost window get the
* event, but it is really meant for the frontmost document window,
* which may be lying behind some tool windows. TGetNextEvent modifies
* the event record to reflect this.
*
* When the event queue doesn't hold any events of its own, we check
* our own two globals toBeDeactivated and toBeActivated,in that order.
* If one of them points to a window, we return an activate event for
* that window.
*
* Finally, if there are no activate events in the queue,but some other
* types, or if the event queue is empty, we simply call GetNextEvent
* and return the result.
*
* Parameters:
*
* IN:
*
* INTEGER eventMask; types of events we want
*
* OUT:
*
* EventRecord *theEvent; event is returned here
*
* Local variables and used functions:
*
* Boolean result, result of GetNextEvent call
* WindowExists(); true if passed window exists
* INTEGER theWKind; window's windowKind
* void HiliteTools(); (Un)highlights all the tools
*
* Global constants and variables:
*
* WindowPeek toBeActivated, window that needs activating
* toBeDeactivated, window that needs deactivating
* frontDocWindow; frontmost document window
* INTEGER deactivFlag; modifiers for a deactivate event
*/
Boolean
TGetNextEvent( eventMask, theEvent )
INTEGER eventMask;
EventRecord *theEvent;
{
Boolean result,
WindowExists();
INTEGER theWKind;
void HiliteTools();
if ( EventAvail( eventMask, theEvent ) != false &&
theEvent->what == activateEvt )
{
/* If there is an official activate event in the queue, get
it with GetNextEvent, and see what caused it. If the
corresponding toBe... flag is the same as the activated
or deactivated window, it was a window that was brought
to the front with SelectWindow or (Get)NewWindow.
In that case the toBe... flag will already have been set
up correctly, so don't do anything. If the (de)activated
window is not equal to the right toBe... flag, it means
a desk accessory was opened or closed. In that case,
pass the event on to the frontmost document window. */
result = GetNextEvent( eventMask, theEvent );
theWKind = TGetWKind(( WindowPtr )theEvent->message );
if (( theEvent->modifiers & activeFlag ) == false )
{
if ( theEvent->message != ( LONGINT )toBeDeactivated )
{
if ( toBeDeactivated != nil )
theEvent->message = ( LONGINT )toBeDeactivated;
else
{
if ( theWKind == userKind ||
theWKind == toolKind )
{
if ( theWKind == toolKind )
HiliteTools( false );
if ( frontDocWindow != nil )
{
HiliteWindow(( WindowPtr )frontDocWindow, false );
theEvent->message = ( LONGINT )frontDocWindow;
}
else
result = TGetNextEvent( eventMask, theEvent );
}
}
}
toBeDeactivated = nil;
}
else
{
if ( theEvent->message != ( LONGINT )toBeActivated )
{
if ( toBeActivated != nil )
theEvent->message = ( LONGINT )toBeActivated;
else
{
if ( theWKind == userKind ||
theWKind == toolKind )
{
if ( theWKind == toolKind )
HiliteTools( true );
if ( frontDocWindow != nil )
{
HiliteWindow(( WindowPtr )frontDocWindow, true );
theEvent->message = ( LONGINT )frontDocWindow;
}
else
result = TGetNextEvent( eventMask, theEvent );
}
}
}
toBeActivated = nil;
}
}
else
{
/* If there is no official activate event, but another type
of event, or perhaps no event at all, first check to see
if one of our toBe... variables is set, meaning that one
of our windows needs activating or deactivating. If so,
fill in the caller's event record with the information
for the (de)activate event. If none of our windows needs
activating or deactivating, just call GetNextEvent to
get a pending event or a null event for the caller. */
if ( toBeDeactivated != nil &&
( eventMask & activMask ) != false )
{
if ( WindowExists( toBeDeactivated ) != false )
{
/* IMPORTANT: check if the window we are about to
deactivate still exists. This won't be a problem
if the window was removed by the TCloseWindow or
TDisposeWindow function (since these functions
remove the deactivate event themselves). It is
necessary if the window belonged to a dialog box
and was removed by CloseDialog or DisposDialog.
Of course they don't clear toBeDeactivated... */
theEvent->what = activateEvt;
theEvent->message = ( LONGINT )toBeDeactivated;
theEvent->modifiers = deactivFlag;
toBeDeactivated = nil;
result = true;
}
else
{
/* The deactivate event was no longer valid,so call
TGetNextEvent again to get a fresh event. And
clear the bogus event of course. */
toBeDeactivated = nil;
result = TGetNextEvent( eventMask, theEvent );
}
}
else if ( toBeActivated != nil &&
( eventMask & activMask ) != false )
{
theEvent->what = activateEvt;
theEvent->message = ( LONGINT )toBeActivated;
theEvent->modifiers = activeFlag;
toBeActivated = nil;
result = true;
}
else
{
result = GetNextEvent( eventMask, theEvent );
}
}
/* Return the result value to indicate if we have an event. */
return( result );
}
/* End of TGetNextEvent */
/*
* W I N D O W E X I S T S
*
* WindowExists determines if the given window is an existing window.
* It traverses the window list and if the window is not found, returns
* false. If the window is found, it returns true.
*
* Parameters:
*
* IN:
*
* WindowPeek thePWindow; window to check for existance
*
* OUT:
*
* Boolean WindowExists(); true if window exists
*
* Local variables and used functions:
*
* WindowPeek loopWindow, to traverse the window list
* Boolean done; true if window exists
*/
Boolean
WindowExists( thePWindow )
WindowPeek thePWindow;
{
WindowPeek loopWindow;
Boolean done;
for ( done = false,
loopWindow = WindowList;
done == false && loopWindow != nil;
loopWindow = loopWindow->nextWindow )
{
if ( loopWindow == thePWindow )
done = true;
}
return( done );
}
/* End of WindowExists */
/*
* G E T W P O S I T I O N
*
* GetWPosition is a utility function to determine the exact position
* of a window with respect to the other windows in the window list. It
* returns a predefined constant describing this position, and another
* constant describing the type of window that is currently frontmost.
*
* GetWPosition starts at the beginning of the window list, and traver-
* ses it until it finds our window. In the meantime, it remembers in
* what state it is, so that when it finds the window, it knows what
* kind of result code to return. There are 10 result codes, correspon-
* ding to the 10 different kinds of positions a window can have.
*
* Parameters:
*
* IN:
*
* WindowPeek thePWindow; window to find position of
*
* OUT:
*
* INTEGER *frontWKind; kind of window currently in front
*
* IN/OUT:
*
* <none>
*
* Local variables and used functions:
*
* WindowPeek theFrontWindow, the frontmost window
* newFrontWindow, new front window after hide
* loopWindow, to traverse the window list
* NextVisWindow(); returns next visible window
* Boolean done; signals end of while loop
* INTEGER result, result code describing position
* loopKind; kind of window during loop
*
* Global variables:
*
* WindowPeek frontToolWindow, frontmost tool window
* backToolWindow, backmost tool window
* frontDocWindow; frontmost document window
*
* Constants:
*
* INTEGER systemKind, windowKind for DA windows
* toolKind, windowKind for tool windows
* anyKind, windowKind "wildcard"
* alone, no other windows visible
* beforeDialog, it is before the frontmost window,
* which is a dialog window
* beforeSystem, it is before the frontmost window,
* which is a system window
* beforeTool, it is before the frontmost window,
* which is a tool window
* beforeDocument, it is before the frontmost window,
* which is a document window
* behindFrontSystem, it is behind the frontmost window,
* which is a system window
* betweenTools, it is among the tool windows
* behindTools, it is behind all the tool windows
* behindSystem, it is behind all the tool windows,
* and behind a system window, but
* before any document windows
* betweenDocuments; it is behind the first document
* window
*/
static INTEGER
GetWPosition( thePWindow, frontWKind )
WindowPeek thePWindow;
INTEGER *frontWKind;
{
WindowPeek theFrontWindow,
newFrontWindow,
loopWindow,
NextVisWindow();
Boolean done;
INTEGER result,
loopWKind;
/* Initialize several variables. */
theFrontWindow = ( WindowPeek )FrontWindow();
/* If our window is visible and the frontmost,
examine the visible window behind ours. */
if ( thePWindow->visible != false &&
theFrontWindow == thePWindow )
newFrontWindow = NextVisWindow( anyKind, theFrontWindow );
else
newFrontWindow = theFrontWindow;
/* If our window is visible, and there are no
windows following it, or if our window is
invisible and there are no visible windows
at all, return right away. */
if ( newFrontWindow == nil )
return( alone );
*frontWKind = TGetWKind(( WindowPtr )newFrontWindow );
if ( thePWindow->visible != false &&
theFrontWindow == thePWindow ||
theFrontWindow == NextVisWindow( anyKind, thePWindow ))
{
/* Our window is visible and the frontmost,
or it's invisible and lying in front of
the frontmost visible window. */
if ( *frontWKind == systemKind )
result = beforeSystem;
else if ( *frontWKind == dialogKind )
result = beforeDialog;
else if ( *frontWKind == toolKind )
result = beforeTool;
else
result = beforeDocument;
}
else
{
/* Our window is not completely in front, but
behind the frontmost visible window. Traverse
the window list, marking every transition to
another category of windows by setting the
result code to the current state. If our
window is invisible, we stop when we find it.
If our window is visible, we stop when we
reach the window in front of it. */
if (thePWindow->visible != false )
thePWindow = PrevVisWindow( thePWindow );
for ( done = false,
loopWindow = theFrontWindow;
done == false;
loopWindow = loopWindow->nextWindow )
{
loopWKind = TGetWKind(( WindowPtr )loopWindow );
if ( loopWindow == theFrontWindow &&
loopWKind == systemKind )
result = behindFrontSystem;
else if ( loopWindow == frontToolWindow &&
backToolWindow != frontToolWindow )
result = betweenTools;
else if ( loopWindow == backToolWindow )
result = behindTools;
else if ( loopWKind == systemKind &&
loopWindow->visible != false &&
result == behindTools )
result = behindSystem;
else if ( loopWindow == frontDocWindow )
result = betweenDocuments;
if ( loopWindow == thePWindow )
done = true;
}
/* Finish by returning the result code. */
return( result );
}
}
/* End of GetWPosition */
/*
* T G E T W K I N D
*
* TGetWKind is a utility function that returns the class of the window
* that is passed to it, based on the WindowRecord's windowKind field.
* TGetWKind returns the constant systemKind if the window is a desk
* accessory, the constant dialogKind if it's a modal dialog or alert
* window, the constant toolKind if it's a tool window, and finally the
* constant userKind for a document window or a modeless dialog window.
*
* TGetWKind simply returns the value of windowKind in most cases (when
* the window is a DA, it always chooses systemKind, and when it is a
* standard window it always chooses userKind, no matter what the real
* value of windowKind may be). It also returns userKind for a modeless
* dialog window.
*
* Parameters:
*
* IN:
*
* WindowPtr theWindow; window to find position of
*
* OUT:
*
* <none>
*
* IN/OUT:
*
* <none>
*
* Local variables:
*
* INTEGER theWKind, windowKind of theWindow
* windowID; windowID of theWindow
* Handle defProc; handle to theWindow's defProc
*
* Global variables:
*
* SysEnvRec theWorld; SysEnvirons record
*
* Constants:
*
* INTEGER systemKind, windowKind for DA windows
* toolKind; windowKind for tool windows
*/
INTEGER
TGetWKind( theWindow )
WindowPtr theWindow;
{
INTEGER theWKind,
varCode,
windowID;
WDEFHandle defProc;
if ( theWindow != nil )
{
theWKind = (( WindowPeek )theWindow )->windowKind;
if ( theWKind <= systemKind )
theWKind = systemKind;
else if ( theWKind == dialogKind )
{
defProc =
( WDEFHandle )(( WindowPeek )theWindow )->windowDefProc;
/* if ( theWorld.machineType == envMac ||
theWorld.machineType == envXL ) */
varCode = ( LONGINT )defProc >> 24 && 0x0000000F;
/* else
varCode = GetWVariant( theWindow ); */
if ( defProc != nil &&
*defProc != nil &&
( *defProc )->type == 'WDEF' )
windowID = ( *defProc )->ID * 16 + varCode;
else
windowID = dBoxProc;
if ( windowID == documentProc ||
windowID == noGrowDocProc ||
windowID == zoomDocProc )
theWKind = userKind;
}
else if ( theWKind == toolKind )
/* nothing */ ;
else if ( theWKind >= userKind )
theWKind = userKind;
}
return( theWKind );
}
/* End of TGetWKind */
/*
* B R I N G T O O L S F O R W A R D
*
* BringToolsForward is used to move a range of visible tool windows further
* to the front. If the behindWindow parameter is inFront, BringToolsForward
* will use SelectWindow to bring the first visible tool window to the front,
* effectively deactivating a desk accessory that may be lying on top. It
* will then traverse the rest of the visible tool windows and bring them
* all behind that first selected one. If the behindWindow parameter is not
* equal to inFront, BringToolsForward will just traverse the visible tool
* windows following behindWindow and move them forward to the new position
* (just behind behindWindow), "across" any desk accessories. Note that the
* BringForward function is passed the postponeCalc parameter. This tells it
* not to call the time-consuming CalcVisBehind function during each move.
* Instead, BringToolsForward saves up all the regions for one call to Calc-
* VisBehind, after all the tools are moved forward.
*
* BringToolsForward returns true if it really encountered visible tool win-
* dows and moved them forward. If there were no tool visible windows at
* all, a result of false is returned.
*
* Parameters:
*
* IN:
*
* WindowPeek thePWindow; move visible tool windows forward
* just behind this window, or to the
* front if it's equal to inFront
* OUT:
*
* Boolean BringToolsForward();true if tools were brought forward
* and the desk accessory deactivated
*
* Local variables and used functions:
*
* WindowPeek NextVisWindow(); returns next visible window
* toolWindow, used for various purposes
* loopWindow; used for various purposes
* void BringForward(); moves a window behind another
*
* Global variables and constants:
*
* INTEGER toolKind; windowKind value for tool windows
* WindowPtr inFront; indicates we want window in front
* WindowPeek toBeActivated, window that needs activating
* frontToolWindow, frontmost tool window
* backToolWindow; backmost tool window
* RgnHandle secondRgn; clobberedRgn for CalcVisBehind
* Boolean postponeCalc; tells BringForward not to call
* CalcVisBehind yet
*/
static Boolean
BringToolsForward( thePWindow )
WindowPeek thePWindow;
{
WindowPeek NextVisWindow(),
toolWindow,
loopWindow;
void BringForward();
if ( thePWindow == ( WindowPeek )inFront )
{
/* Find the frontmost tool window behind the DA(s). */
toolWindow = NextVisWindow( toolKind, ( WindowPeek )FrontWindow() );
/* If it's not nil, we use SelectWindow to bring it in
front (and to deactivate the desk accessory). Back-
ToolWindow and frontToolWindow are initialized, and
loopWindow is prepared for traversing the remaining
visible tool windows. */
if ( toolWindow != nil )
{
loopWindow = toolWindow->nextWindow;
SelectWindow(( WindowPtr )toolWindow );
frontToolWindow =
backToolWindow = toolWindow;
}
/* If it's nil, it means there are no visible tool
windows. Return with false to indicate that there
are no tool windows visible and that the topmost DA
has not been deactivated yet. */
else
{
return( false );
}
}
/* Set up loopWindow and backToolWindow to start moving
the visible tool windows behind thePWindow forward. */
else
{
loopWindow = thePWindow->nextWindow;
backToolWindow = thePWindow;
}
/* Traverse the rest of the visible tool windows,
and move them just behind backToolWindow, across
the DA(s). Add each tool window's strucRgn to
the region that will be used for one call to
CalcVisBehind. */
SetEmptyRgn( secondRgn );
thePWindow = nil;
while ( loopWindow != nil )
{
if ( loopWindow->windowKind == toolKind &&
loopWindow->visible != false )
{
toolWindow = loopWindow;
toolWindow->hilited = true;
BringForward( toolWindow, backToolWindow, postponeCalc );
UnionRgn( secondRgn, toolWindow->strucRgn, secondRgn );
backToolWindow = toolWindow;
if ( thePWindow == nil )
thePWindow = toolWindow;
}
loopWindow = loopWindow->nextWindow;
}
CalcVisBehind( thePWindow, secondRgn );
SetEmptyRgn( secondRgn );
/* Return true to indicate that there are actually
tool windows visible (and that all of those
visible windows were moved). */
return( true );
}
/* End of BringToolsForward */
/*
* N E X T V I S W I N D O W
*
* NextVisWindow returns the next visible window of type wantedKind following
* thePWindow. It traverses the window list, skipping invisible windows and
* windows of the wrong type, until it finds this type of window. If it does
* not find a next visible window, nil is returned.
*
* It is allowed to pass the constant inFront as thePWindow; searching will
* then commence with the frontmost visible window. If wantedKind is equal
* to the predefined constant anyKind, NextVisWindow returns the next visible
* window, no matter what kind.
*
* Parameters:
*
* IN:
*
* INTEGER wantedKind; kind of window to look for
* WindowPeek thePWindow; window to start looking behind
*
* OUT:
*
* WindowPeek NextVisWindow(); first visible wantedKind window
* behind thePWindow or nil
*
* Local variables and used functions:
*
* WindowPeek loopWindow, used for various purposes
* wantedWindow; window to look for; end of for loop
*
* Constants:
*
* INTEGER anyKind; windowKind "wildcard"
* WindowPtr inFront; indicates we want window in front
*/
static WindowPeek
NextVisWindow( wantedKind, thePWindow )
INTEGER wantedKind;
WindowPeek thePWindow;
{
WindowPeek loopWindow,
wantedWindow;
/* If thePWindow is equal to the predefined constant
inFront, set it to FrontWindow(). Check if this is
possibly the window we're looking for. If yes, return
it. If no, fall through to the loop below. */
if ( thePWindow == ( WindowPeek )inFront )
{
thePWindow = ( WindowPeek )FrontWindow();
if ( thePWindow == nil )
return( thePWindow );
else if ( wantedKind == anyKind ||
wantedKind == TGetWKind(( WindowPtr )thePWindow ))
return( thePWindow );
}
/* Traverse the window list, starting with the window
following thePWindow, in search of the frontmost
visible wantedKind type window. */
for ( wantedWindow = nil,
loopWindow = thePWindow->nextWindow;
wantedWindow == nil &&
loopWindow != nil;
loopWindow = loopWindow->nextWindow )
{
if ( loopWindow->visible != false )
if ( wantedKind == anyKind ||
wantedKind == TGetWKind(( WindowPtr )loopWindow ))
wantedWindow = loopWindow;
}
return( wantedWindow );
}
/* End of NextVisWindow */
/*
* P R E V V I S W I N D O W
*
* PrevVisWindow returns the next visible window in front of thePWindow in
* the window list. It traverses the window list until it finds this window.
* If there is no such window, PrevVisWindow returns nil.
*
* Parameters:
*
* IN:
*
* WindowPeek thePWindow; window to find previous visible for
*
* OUT:
*
* WindowPeek PrevVisWindow(); first visible window in front of
* thePWindow, or nil if none
*
* Local variables and used functions:
*
* WindowPeek loopWindow, used for various purposes
* prevWindow, candidate for previous visible window
* theFrontWindow, frontmost visible window
* NextVisWindow(); next visible window in window list
* Boolean done; signals end of while loop
*
* Constants:
*
* INTEGER anyKind; windowKind "wildcard"
*/
static WindowPeek
PrevVisWindow( thePWindow )
WindowPeek thePWindow;
{
WindowPeek loopWindow,
prevWindow,
theFrontWindow,
NextVisWindow();
Boolean done;
theFrontWindow = ( WindowPeek )FrontWindow();
/* If thePWindow is the frontmost visible or even
frontmost invisible window, return nil. */
if ( thePWindow == theFrontWindow ||
theFrontWindow == NextVisWindow( anyKind, thePWindow ))
return(( WindowPeek )nil );
/* Traverse the window list, starting with the
frontmost visible window, and see if one of
the windows following it up to (and including)
the next visible window is our window. If not,
move to the next visible window. */
prevWindow = theFrontWindow;
loopWindow = prevWindow->nextWindow;
done = false;
while ( done == false )
{
if ( loopWindow == thePWindow )
done = true;
else
if ( loopWindow->visible != false )
prevWindow = loopWindow;
loopWindow = loopWindow->nextWindow;
}
return( prevWindow );
}
/* End of PrevVisWindow */
/*
* B R I N G F O R W A R D
*
* BringForward is a special function to move a window further to the front.
* The move is accomplished by three calls to the Window Manager: SendBehind
* to move the window, PaintOne to paint the newly uncovered content region,
* and finally - if waitWithCalc is not true - CalcVisBehind to recalculate
* the visRgns of all the windows behind our window. NOTE: Inside Macintosh
* (page I-286) mentions that a call to SendBehind in a case like this must
* be followed by calls to the routines PaintOne and CalcVis. However, Calc-
* Vis just isn't enough here: we need to recalculate the visRgns of _all_
* windows behind our window.
*
* Parameters:
*
* IN:
*
* WindowPeek thePWindow, window that needs to be moved forward
* behindWindow; ... behind this window
* Boolean waitWithCalc; if true, dont call CalcVisBehind
*
* Global variables:
*
* RgnHandle firstRgn; uncovered region of window to redraw
*/
static void
BringForward( thePWindow, behindWindow, waitWithCalc )
WindowPeek thePWindow;
WindowPeek behindWindow;
Boolean waitWithCalc;
{
/* The newly exposed part of the structure region of our window
is calculated (remember that visRgn is in local coordinates). */
CopyRgn ( thePWindow->strucRgn, firstRgn );
OffsetRgn( thePWindow->port.visRgn,
- thePWindow->port.portBits.bounds.left,
- thePWindow->port.portBits.bounds.top );
DiffRgn ( firstRgn, thePWindow->port.visRgn, firstRgn );
OffsetRgn( thePWindow->port.visRgn,
thePWindow->port.portBits.bounds.left,
thePWindow->port.portBits.bounds.top );
/* Move the window to its new position, paint the newly
exposed part of of the window's contents white, and
recalculate the lower windows' visRgns. */
SendBehind(( WindowPtr )thePWindow, ( WindowPtr )behindWindow );
PaintOne ( thePWindow, firstRgn );
if ( waitWithCalc == false )
CalcVisBehind( thePWindow, thePWindow->strucRgn );
SetEmptyRgn( firstRgn );
}
/* End of BringForward */
/*
* H I L I T E T O O L S
*
* HiliteTools is a utility function that highlights or unhighlights all the
* tool windows that are visible. Its main purpose is to unhighlight the
* tools whenever a window that doesn't belong to the application is brought
* to the front,or to highlight the tools when such a window is removed from
* the frontmost position. This can be a desk accessory when running the
* standard Mac operating system, or can be any application's window when
* running under MultiFinder.
*
* Parameters:
*
* IN:
*
* Boolean hilite; true = hilite, false = unhilite
*
* Local variables and used functions:
*
* WindowPeek loopWindow; used to traverse windows
* Boolean done; signals end of while loop
*
* Global variables:
*
* WindowPeek frontToolWindow, frontmost tool window
* backToolWindow; backmost tool window
*/
static void
HiliteTools( hilite )
Boolean hilite;
{
WindowPeek loopWindow;
Boolean done;
if ( frontToolWindow != nil )
{
for ( done = false,
loopWindow = frontToolWindow;
done == false && loopWindow != nil;
loopWindow = loopWindow->nextWindow )
{
if ( TGetWKind(( WindowPtr )loopWindow ) == toolKind &&
loopWindow->visible != false )
{
HiliteWindow(( WindowPtr )loopWindow, hilite );
if ( loopWindow == backToolWindow )
done = true;
}
}
}
}
/* End of HiliteTools */